import * as $array from "./06-Array";
import * as $type from "./02-Type";
import { Optional } from "./02-Type";

export interface IDisposer {
  isDisposed(): boolean;
  dispose(): void;
}

export class Disposer implements IDisposer {
  private _disposed: boolean;

  private _dispose: () => void;

  constructor(dispose: () => void) {
    // console.log(dispose());
    // console.log("hhhhh", dispose);
    this._disposed = false;
    this._dispose = dispose;
  }
  public dispose(): void {
    // console.log("this的指向", this);
    if (!this._disposed) {
      this._disposed = true;
      this._dispose();
    }
  }
  public isDisposed(): boolean {
    return this._disposed;
  }
}
// super 是什么 https://www.jianshu.com/p/2a5a7352f4e5
export class MultiDisposer extends Disposer {
  constructor(disposer: Array<IDisposer>) {
    //   super 相当于 父级的构造函数 将父级所拥有的属性和方法 通过该方法继承给子类
    super(() => {
      $array.each(disposer, (x) => {
        x.dispose();
      });
    });
    // const superFunc = () => {
    //   disposer.forEach((x, index) => {
    //     // console.log("super里面的方法", x, index);
    //     x.dispose();
    //   });
    // };
    // console.log("我下面是super");
    // super(superFunc);
    // console.log("我上面是super");
  }
  //   原型链的 寻找规律
  //   dispose() {
  //     console.log("重写了父类的dispose,则不会在去找父类的dispose方法");
  //   }
}

// const aFunc = () => console.log("a-disposer-方法调用");
// const bFunc = () => console.log("bbbbb-disposer-方法调用");
// const aDisposer = new Disposer(aFunc);
// // console.log("a", aDisposer.isDisposed());
// const bDisposer = new Disposer(bFunc);
// // console.log("b", bDisposer.isDisposed());

// const bMulList = new MultiDisposer([aDisposer, bDisposer]);
// console.log("创建完毕");
// // aDisposer.dispose();
// bMulList.dispose();

export class MutableValueDisposer<T extends IDisposer> extends Disposer {
  private _disposer: Optional<IDisposer>;

  private _value: Optional<T>;

  constructor() {
    super(() => {
      if ($type.hasValue(this._disposer)) {
        this._disposer.dispose();
        this._disposer = undefined;
      }
    });
  }
  public get(): Optional<T> {
    return this._value;
  }
  public set(value: Optional<T>, disposer: Optional<IDisposer>): void {
    if ($type.hasValue(this._disposer)) {
      this._disposer.dispose();
    }
    this._disposer = disposer;
    this._value = value;
  }
  public reser(): void {
    this.set(undefined, undefined);
  }
}

export class CounterDisposer extends Disposer {
  private _counter: number = 0;
  public increment() {
    ++this._counter;
    return new Disposer(() => {
      --this._counter;
      if (this._counter === 0) {
        this.dispose();
      }
    });
  }
}
